import java.io.*;
import java.net.*;
import java.util.*;
import java.math.*;
import java.text.SimpleDateFormat;
import java.security.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.codec.binary.Base64;

class TraitementClient extends Thread {
	static int numeroDeThread = 0;
	static Date dateDeDebut;
	static HashMap<String, String[]> cache = new HashMap<String, String[]>();
	static HashMap<String, String[]> ssidConnected = new HashMap<String, String[]>();
	static int nombreDeThreads = 0;
	static int nombreMaxDeThreads = 0;
	static long nombreDeBytes = 0;
	static SessionIdentifierGenerator sig = new SessionIdentifierGenerator();
	static String cookie = sig.nextSessionId();
	static String enteteToUse = "";
	static String enteteHTTP = "HTTP/1.1 200 OK\n" +
					"Date: jeudi matin 8 fevrier 2007\n" +
					"Set-Cookie: ssid=" + cookie + "\n" +
					"Content-Type: text/html\n"+"\n" ;
	static String enteteHTTP302 = "HTTP/1.1 302 OK\n" +
					"Date: jeudi matin 8 fevrier 2007\n" +
					"Location: @@urlNeeded@@\n" +
					"Content-Type: text/html\n"+"\n" ;
	Socket socket;
        
	TraitementClient (Socket s) {
		socket = s;
	}
	public void run() {
		try {
			if (TraitementClient.nombreDeThreads>TraitementClient.nombreMaxDeThreads) 
				TraitementClient.nombreMaxDeThreads = TraitementClient.nombreDeThreads;
			InputStream socketInputStream = socket.getInputStream();
			byte[] dataRecueSurLaSocket = new byte[8096];
	
			int taille = socketInputStream.read(dataRecueSurLaSocket);
			String requeteDuClient = new String(dataRecueSurLaSocket,0,taille);
			String mots[] = requeteDuClient.split(" ");
			String httpPost[] = requeteDuClient.split("\n\r\n");

			//CHECKING URL 
			String urlType[] = requeteDuClient.split(" ");
			System.out.println("Requete : " + urlType[0] + " " + urlType[1]);
			UrlModify urlModify = new UrlModify(mots[1], cache, ssidConnected, cookie, dateDeDebut);
			urlModify.urlCase(httpPost, urlModify.urlNeeded);

			byte[] dataLueSurLeFichier = new byte[8196];
			OutputStream socketOutputStream = socket.getOutputStream();
			if(!urlModify.redirect){
				enteteToUse = enteteHTTP;
			} else {
				enteteToUse = enteteHTTP302.replace("@@urlNeeded@@", urlModify.urlNeeded);
			}
			socketOutputStream.write(TraitementClient.enteteToUse.getBytes()); //very important!

			//evité d'encodé les fonts custom^^ pck ca bug sinon!!!!!!!!!!!
			if(urlModify.urlNeeded.contains(".ttf")){
				FileInputStream fileContentStream = new FileInputStream("." + urlModify.urlNeeded);
				taille = fileContentStream.read(dataLueSurLeFichier);
				TraitementClient.nombreDeBytes += taille;
				while (taille != -1) {
					socketOutputStream.write(dataLueSurLeFichier,0,taille);
					taille = fileContentStream.read(dataLueSurLeFichier);
					TraitementClient.nombreDeBytes += taille;
				}
			}
			else {
				FileInputStream cacheFile = new FileInputStream("." + urlModify.urlNeeded);			
				String fileContent = urlModify.isCached(cacheFile);
				if(urlModify.urlNeeded.matches("(.*/)*.+\\.(png|jpg|gif|jpeg|PNG|JPG|GIF)$")){
					byte[] imageByteArray = urlModify.decodeImage(fileContent);
					socketOutputStream.write(imageByteArray);
				}
				else {
					InputStream  fileContentStream = new ByteArrayInputStream(fileContent.getBytes("ISO-8859-1"));
					taille = fileContentStream.read(dataLueSurLeFichier);
					TraitementClient.nombreDeBytes += taille;
					while (taille != -1) {
						socketOutputStream.write(dataLueSurLeFichier,0,taille);
						taille = fileContentStream.read(dataLueSurLeFichier);
						TraitementClient.nombreDeBytes += taille;
					}
				}
			}
			getAllClassVar(urlModify);
			/*FakeFirewall fake = FakeFirewall.getInstance();
			fake.analyze(params);*/
			socket.close();
		}
		catch (Exception e) {}
		TraitementClient.nombreDeThreads--;
	}

	public void getAllClassVar(UrlModify url){
		cache = url.getCache();
		ssidConnected = url.getSSID();
		cookie = url.getCookie();
	}
        
	public static int urlFrom(String requeteDuClient) {
		String urlType[] = requeteDuClient.split(" ");
		String page = urlType[1];
		int type;
		if(urlType[0] == "GET")
			type = 1;
		else if(urlType[0] == "POST")
			type = 2;
		else type = -1;

		if (page == "/index.html" && type == 1 )
			return 1;
		else if (page == "/index.html" && type == 2 )
			return 2;
		else return -1;
	}
}

public class ServeurHTTP {
	static FakeFirewall fake = FakeFirewall.getInstance();

	public static void main(String[] args) throws Exception {
		int port = args.length>0 ? Integer.parseInt(args[0]) : 150;
		ServerSocket serverSocket = new ServerSocket(port);
		TraitementClient.dateDeDebut = new Date();

                    while (true) {
                        Socket socket = serverSocket.accept();
                        TraitementClient thread = new TraitementClient(socket);
                        thread.start();
                    }
	}
}
